import ssl,json
import websockets
import asyncio
from flask import Flask,template_rendered,render_template, request, jsonify
from flask_socketio import SocketIO
from flask_cors import CORS
import configparser
from datetime import datetime

app = Flask(__name__)
CORS(app)  # 允许所有的 CORS 请求
socketio = SocketIO(app,cors_allowed_origins='*')

config = configparser.ConfigParser()
config.read('key.ini')
# key.ini文件中的内容应该如下：
# [AzureOpenai]
# azure_endpoint = https://XXXXXXXX.openai.azure.com
# api_version = 2024-10-01-preview
# api_key = XXXXXXXXXXXXXXXXXXXXXXX
# deployment_name = gpt-4o-realtime-preview

configsection = config['AzureOpenai']
azure_endpoint = configsection["azure_endpoint"]
api_version = configsection["api_version"]
api_key = configsection["api_key"]
deployment_name = configsection["deployment_name"]
azure_endpoint = azure_endpoint.replace("https://","wss://")
uri = f"{azure_endpoint}/openai/realtime?api-version={api_version}&deployment={deployment_name}&api-key={api_key}"

instructions = """
你是一个中国学生的英语教师，请和他进行交流，帮助他提升口语。
"""

async def chat(audio_base64,sid,instructions_text="你是一个友善的聊天助手，请使用中文和我聊天。"):
    # print("Sending audio to Azure OpenAI")
    ssl_context = ssl._create_unverified_context()  # 创建不验证证书的SSL上下文
    print("当前system：",instructions_text)
    async with websockets.connect(uri, ssl=ssl_context) as websocket:
        try:
            # 发送 session.update 事件来配置会话
            session_update = {
                "type": "session.update",
                "session": {
                    "voice": "alloy",
                    "instructions": instructions_text,
                    "input_audio_format": "pcm16",
                    "output_audio_format": "pcm16",
                    "input_audio_transcription": {
                        "model": "whisper-1"
                    },
                    "turn_detection": {
                        "threshold": 0.4,
                        "silence_duration_ms": 600,
                        "type": "server_vad"
                    }
                }
            }
            await websocket.send(json.dumps(session_update))

            # 创建并发送 input_audio_buffer.append 消息
            append_message = {"type": "input_audio_buffer.append","audio": audio_base64}
            await websocket.send(json.dumps(append_message))

            # 创建并发送 input_audio_buffer.commit 消息
            commit_message = {"type": "input_audio_buffer.commit"}
            await websocket.send(json.dumps(commit_message))

            response_create = {"type": "response.create"}
            await websocket.send(json.dumps(response_create))

            while True:
                # 接收服务端的回应
                response = await websocket.recv()
                
                response_json = json.loads(response)
                response_json["nowtime"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

                logfilepath = "log/" + response_json["type"] + ".json"

                with open(logfilepath, "a", encoding='utf-8') as f:
                    json.dump(response_json, f, ensure_ascii=False, indent=4)

                if response_json["type"] == "response.done":
                    # print("\n一次对话结束。")
                    break
                elif response_json["type"] == "conversation.item.input_audio_transcription.completed":
                    # print("\n输入的语音转录的文本内容。")
                    transcript_res = response_json["transcript"].rstrip()
                    display_text = f"我：{transcript_res}"
                    print(display_text)
                    socketio.emit('dialogue',display_text,to=sid)
                elif response_json["type"] == "response.audio.delta":
                    # print("\n生成的语音片段。")
                    audio_res = response_json["delta"]
                    socketio.emit('audio', audio_res,to=sid)
                elif response_json["type"] == "response.audio_transcript.delta":
                    # print("\n生成的文字片段。")
                    pass
                elif response_json["type"] == "response.output_item.done":
                    # print("\n输出的语音转录的文本内容。")
                    text_res = response_json["item"]["content"][0]["transcript"]
                    display_text = f"AI：{text_res}"
                    print(display_text)
                    socketio.emit('dialogue',display_text,to=sid)
                elif response_json["type"] == "error":
                    # print("\n错误信息内容。")
                    error_res = response_json["error"]["message"]
                    error_text = f"error：{error_res}"
                    print(error_text)
                    socketio.emit('dialogue',error_text,to=sid)

        except websockets.exceptions.ConnectionClosed as e:
            print(f"Connection closed: {e}")

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload_audio', methods=['POST'])
def upload_audio():
    data = request.get_json()  # 获取 JSON 数据
    if 'audio' in data:
        audio_base64 = data['audio']
        sid = data['sid']
        instructions_text = data['instructions_text']
        if not(instructions_text):
            instructions_text = "你是一个友善的聊天助手，请使用中文和我聊天。"
        asyncio.run(chat(audio_base64,sid,instructions_text))
        return jsonify({'message': '音频数据已接收'}), 200
    else:
        return jsonify({'error': '未找到音频数据'}), 400

@app.route('/airoleoptions', methods=['GET'])
def get_airoleoptions():
    try:
        # 从文件中读取JSON数据
        with open('airole.json', 'r', encoding='utf-8') as f:
            options = json.load(f)
        return jsonify(options)
    except Exception as e:
        # 如果读取文件失败，返回错误消息
        return jsonify({'error': str(e)}), 500

@socketio.on('connect')
def handle_connect():
    sid = request.sid  # type: ignore # 获取客户端的会话 ID
    socketio.emit('receive_sid', {'sid': sid})
    print(f'Client connected,sid:{sid}')

@socketio.on('disconnect')
def handle_disconnect():
    print('Client disconnected')

if __name__ == "__main__":
    # 本地运行
    # socketio.run(app,host="127.0.0.1" ,debug=False, port=5000)

    # 局域网服务器运行
    context = ('cert.pem', 'key.pem')  # 指定证书和私钥文件
    socketio.run(app,host="0.0.0.0" ,debug=False, port=5002, ssl_context=context)
